import hashlib
import random
import tkinter as tk
from tkinter import *
from tkinter import messagebox,filedialog
from tkinter.ttk import *
# from PasswordMsgBox import *
import configparser
from spcparser import *
import os
import sys

class FormAdmin(Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.master = master
        # self.master.geometry("1000x800")
        self.pack()
        self.master.title("管理员专用")
        # 关联关闭事件
        self.master.protocol("WM_DELETE_WINDOW", self.close)
        # self.create_widgets()
        self.Group0 = LabelFrame(self, text="选择文件/choose file")
        self.Group0.grid(row=0, column=0, columnspan=5, sticky='WNS', padx=(10, 10), pady=(5, 5))
        
        self.label1 = Label(self.Group0, text="单个文件路径/Source File Path:")
        self.label1.grid(row=0, column=0, sticky='WNS', padx=(0, 10), pady=(5, 5))
        self.EntrySingleFilePath = Entry(self.Group0, width=45,)
        self.EntrySingleFilePath.grid(row=0, column=1, sticky='WNS', padx=(0, 10), pady=(5, 0))
        self.BtnChooseSingleFile = Button(self.Group0, text="...", command=self.chooseSingleFile)
        self.BtnChooseSingleFile.grid(row=0, column=2, sticky='WNS', padx=(0, 10), pady=(5, 0))
        self.BtnRunSingleFile = Button(self.Group0, text="分析列/get columns", command=self.runSingleFile)
        self.BtnRunSingleFile.grid(row=0, column=3, sticky='WNS', padx=(0, 10), pady=(5, 0))
        
        self.Group1 = LabelFrame(self, text="程序信息/Program")
        self.Group1.grid(row=1, column=0, columnspan=5, sticky='WNS', padx=(10, 10), pady=(5, 5))
        self.text1 = Text(self.Group1, width=205, height=3)
        self.text1.insert(END, "")
        self.text1.pack(side=LEFT, padx=(10, 5), pady=(5, 5))
        
        self.Group2 = LabelFrame(self, text="SPC 信息/SPC INFO")
        self.Group2.grid(row=2, column=0, columnspan=5, sticky='WNS', padx=(10, 10), pady=(5, 5))
        self.text2 = Text(self.Group2, width=205, height=3)
        self.text2.insert(END, "")
        self.text2.pack(side=LEFT, padx=(10, 5), pady=(5, 5))
        
        self.Group3 = LabelFrame(self, text="设置NG 格式/NG FORMAT")
        self.Group3.grid(row=3, column=0, columnspan=5, sticky='WNS', padx=(10, 10), pady=(5, 5))
        self.text_ng_format = Text(self.Group3, width=205, height=3)

        self.text_ng_format.pack(side=TOP, padx=(10, 5), pady=(5, 5))
        self.btn_ng_test = Button(self.Group3, text="测试ng输出效果", command=self.tryNgFormat)
        self.btn_ng_save = Button(self.Group3, text="保存ng格式", command=self.saveNgFormat)
        self.btn_ng_default = Button(self.Group3, text="显示为默认", command=self.setNgDefault)
        # 增加一个label，红色文字
        self.lbl_ng_test = Label(self.Group3, text="表里的字段从上边复制，自定义数据使用英文双引号，多个数据可以使用逗号分割，也可使用||拼接,注意使用英语符号！", foreground="red")
        # 把测试效果和保存按钮加入到Group3,并放到新的一行
        self.btn_ng_test.pack(side=LEFT,padx=(5, 5), pady=(5, 5))
        self.btn_ng_save.pack(side=LEFT,padx=(5, 5), pady=(5, 5))
        self.btn_ng_default.pack(side=LEFT,padx=(5, 5), pady=(5, 5))
        self.lbl_ng_test.pack(side=LEFT,padx=(5, 5), pady=(5, 5))
        
        self.Group4 = LabelFrame(self, text="设置OK 格式/OK FORMAT")
        self.Group4.grid(row=4, column=0, columnspan=5, sticky='WNS', padx=(10, 10), pady=(5, 5))
        self.text_ok_format = Text(self.Group4, width=205, height=3)
        self.text_ok_format.pack(side=TOP, padx=(10, 5), pady=(5, 5))
        self.btn_ok_test = Button(self.Group4, text="测试ok输出效果", command=self.tryOkFormat)
        self.btn_ok_save = Button(self.Group4, text="保存ok格式", command=self.saveOkFormat)
        self.btn_ok_default = Button(self.Group4, text="显示为默认", command=self.setOkDefault)
        
        # 把测试效果和保存按钮加入到Group4,并放到新的一行
        self.btn_ok_test.pack(side=LEFT,padx=(5, 5), pady=(5, 5))
        self.btn_ok_save.pack(side=LEFT,padx=(5, 5), pady=(5, 5))
        self.btn_ok_default.pack(side=LEFT,padx=(5, 5), pady=(5, 5))
        
        self.Group5 = LabelFrame(self, text="测试效果：")
        self.Group5.grid(row=5, column=0, columnspan=5, sticky='WNS', padx=(10, 10), pady=(5, 5))
        self.text_test = Text(self.Group5, width=205, height=8)
        self.text_test.pack(side=LEFT,padx=(5, 5), pady=(5, 5))
        
        # 路径设置 group
        self.GroupPaths = LabelFrame(self, text="路径设置：/set path")
        self.GroupPaths.grid(row=6, column=0, columnspan=10, sticky='WNS', padx=(10, 10), pady=(5, 5))
        
        # region 设置路径
        self.labelSFP = Label(self.GroupPaths, text="源路径：")
        self.labelDFP = Label(self.GroupPaths, text="目标路径：")
        self.labelEFP = Label(self.GroupPaths, text="错误路径：")
        self.labelPFP = Label(self.GroupPaths, text="图片路径：")
        
        self.EntrySFP = Entry(self.GroupPaths,width=45)
        self.EntryDFP = Entry(self.GroupPaths,width=45)
        self.EntryEFP = Entry(self.GroupPaths,width=45)
        self.EntryPFP = Entry(self.GroupPaths,width=45)
        
        self.ButtonSFP = Button(self.GroupPaths, text="浏览", command=self.chooseSFPPath)
        self.ButtonDFP = Button(self.GroupPaths, text="浏览", command=self.chooseDFPPath)
        self.ButtonEFP = Button(self.GroupPaths, text="浏览", command=self.chooseEFPPath)
        self.ButtonPFP = Button(self.GroupPaths, text="浏览", command=self.choosePFPPath)
        
        self.labelSFP.grid(row=0, column=0, sticky=W)
        self.EntrySFP.grid(row=0, column=1, sticky=W)
        self.ButtonSFP.grid(row=0, column=2, sticky=W)
        
        self.labelDFP.grid(row=1, column=0, sticky=W)
        self.EntryDFP.grid(row=1, column=1, sticky=W)
        self.ButtonDFP.grid(row=1, column=2, sticky=W)
        
        self.labelEFP.grid(row=2, column=0, sticky=W)
        self.EntryEFP.grid(row=2, column=1, sticky=W)
        self.ButtonEFP.grid(row=2, column=2, sticky=W)   
             
        self.labelPFP.grid(row=3, column=0, sticky=W)
        self.EntryPFP.grid(row=3, column=1, sticky=W)
        self.ButtonPFP.grid(row=3, column=2, sticky=W)
        # endregion

        # region 设置 admin 密码
        self.labelAdminPassword = Label(self.GroupPaths, text="管理员密码/admin password:")
        self.EntryAdminPassword = Entry(self.GroupPaths)
        self.labelAdminPassword.grid(row=0, column=3, sticky="W")
        self.EntryAdminPassword.grid(row=0, column=4, sticky="EW")
        # endregion

        # region 设置 user 密码
        self.labelUserPassword = Label(self.GroupPaths, text="用户密码/user password:")
        self.EntryUserPassword = Entry(self.GroupPaths)
        self.labelUserPassword.grid(row=1, column=3, sticky="W")
        self.EntryUserPassword.grid(row=1, column=4, sticky="EW")
        # endregion
        
        # region 设置 间隔时间
        self.labelSeconds = Label(self.GroupPaths, text="数据提取间隔秒数/get data seconds:")
    
        # self.scaleSeconds = Scale(self.GroupPaths, from_=1, to=60, orient=HORIZONTAL,tickinterval=1, showvalue=True)
        self.spinboxSeconds = Spinbox(self.GroupPaths, from_=1, to=10, increment=1, wrap=True)
        self.labelSeconds.grid(row=2, column=3, sticky=W)
        self.spinboxSeconds.grid(row=2, column=4, sticky='EW')
        # endregion
        
        # region 保存按钮
        self.saveBtn = Button(self.GroupPaths, text="保存/save", command=self.save)
        self.saveBtn.grid(row=0, rowspan=3, column=5, sticky='NSEW',)
        # endregion
        
        self.init_config()
    # region form 的方法    
    def init_config(self):
        self.config_file = 'config.ini'
        self.config = configparser.ConfigParser()
        if os.path.exists(self.config_file):
            self.config.read(self.config_file,encoding='utf-8')
            Passformat = self.config.get('FMT', 'Pass')
            if not Passformat:
                self.config.set('FMT', 'Pass', '"TEST:"||[ProgramName],[BoardID],[BoardID]||[BlockNo],[StartTime],[MachineName],"NoData","Pass",[OPJudge],[Lot]')
                self.save_config()
                self.config.read(self.config_file,encoding='utf-8')
            
            Failformat = self.config.get('FMT', 'Fail')
            if not Failformat:
                self.config.set('FMT', 'Fail', '"TEST:"||[ProgramName],[BoardID],[BoardID]||[BlockNo],[StartTime],[MachineName],"NoData","Fail",[OPJudge],[PartsName] as LibPartsName,[RefName],[StepCenterX],[StepCenterY],[NgReason],[BlockNo],[LaneNo],[RSOperatorName],[ImageFile] as newImageFile,[Lot]')
                self.save_config()
                self.config.read(self.config_file,encoding='utf-8')
                
            #读取 path 配置中的 spath dpath epath 值
            spath = self.config.get('PATH', 'spath')
            dpath = self.config.get('PATH', 'dpath')
            epath = self.config.get('PATH', 'epath')
            ppath = self.config.get('PATH', 'ppath')
            # 把路径 显示到 界面上   self.EntrySFP  self.EntryDFP  self.EntryEFP
            self.EntrySFP.insert(0, spath)
            self.EntryDFP.insert(0, dpath)
            self.EntryEFP.insert(0, epath)
            self.EntryPFP.insert(0, ppath)

            seconds = self.config.get('TIME', 'seconds')
            self.spinboxSeconds.insert(0, seconds)
            
            
            t = self.config.get("FMT","Fail")
            self.text_ng_format.insert(END, t)

            t = self.config.get("FMT","Pass")
            self.text_ok_format.insert(END, t)
        else:
            messagebox.showinfo('提示', '没找到配置文件！/Not found config file!')
            sys.exit()
    
    def save_config(self):
        # 将更改写入文件
        with open(self.config_file, 'w',encoding='utf-8') as configfile:
            self.config.write(configfile)
    
    def close(self):
        '''
        关闭窗口事件
        '''
        self.master.destroy()
        # custom_dialog = PasswordBox(self.master)
        # result, password = custom_dialog.show()
        # if result and len(password):
        #     messagebox.showinfo("Success", f"You entered: {password}")
        #     self.master.destroy()

    def chooseSingleFile(self):
        '''
        弹出一个选择csv文件的对话框,把结果写到输入框EntrySingleFilePath中
        '''
        file_path = filedialog.askopenfilename(
            title='选择CSV文件',
            filetypes=[('CSV files', '*.csv')]
        )
        
        # 如果用户选择了文件，将文件路径设置到Entry组件中
        if file_path:
            self.EntrySingleFilePath.delete(0, END)  # 清空Entry组件的内容
            self.EntrySingleFilePath.insert(0, file_path)  # 插入所选文件的路径  
        
    def runSingleFile(self):
        '''
        分析单个文件，把文件中的列写入到文本框里
        '''
        # 获取输入框中的文件路径
        file_path = self.EntrySingleFilePath.get()
        if not file_path:
            return
        fields={}
        try:
            with open(file_path, 'r',encoding='utf8') as f:
                for line in f:
                    if line.startswith('ProgramNo'):
                        fields['ProgramFields'] = line.strip().replace(',','],[') 
                    if line.startswith('RefNo'):
                        fields['RefFields'] = line.strip().replace(',','],[') 
                        break
        except Exception as ex :
            # 使用messagebox 显示 ex中的 错误
            messagebox.showerror('错误',ex)
            return
        # 把 fields['ProgramFields'] 写入到 self.text1
        self.text1.delete(1.0, tk.END)
        self.text1.insert(tk.END, '['+fields['ProgramFields']+"]")
        # 清空self.text2，再把 fields['RefFields'] 写入到 self.text1
        self.text2.delete(1.0, tk.END)
        self.text2.insert(tk.END, '['+fields['RefFields']+"]")

    def tryNgFormat(self):
        '''
        测试 NG 格式效果
        '''
        self.text_test.delete("1.0",tk.END)
        
        # 获取EntrySingleFilePath 的值
        spc_fullname = self.EntrySingleFilePath.get()
        s = "开始 "+os.path.basename(spc_fullname)+" 的 ng格式测试\n"
        self.text_test.insert(tk.END,s)
        file_info,cursor="",""
        try:
            file_info,cursor = parse_scp(spc_fullname)
            self.text_test.insert(tk.END,"ng 格式:\n")
        except Exception  as ex:
            self.text_test.insert(tk.END,"分析文件出错:\n")
            self.text_test.insert(tk.END,ex)
            self.text_test.insert(tk.END,"\n")
            return
        
        # 获取 self.text_ng_format 的text值
        ng_format = self.text_ng_format.get("1.0",tk.END)
        ng_format = ng_format.strip()
        ng_format = ng_format.replace('\n',' ')
        ng_format = ng_format.strip(',')
        r = ngRows(ng_format,cursor)
        # 如果r是列表，则 拼接成 字符串
        if isinstance(r,list):
            for i in r:
                self.text_test.insert(tk.END,",".join(i)+"\n")
        else:
            self.text_test.insert(tk.END,r+"\n")
        #  把 r 写入 self.text_test

        self.text_test.insert(tk.END,"\n分析结束\n")
        
    def tryOkFormat(self):
        '''
        测试 NG 格式效果
        '''
        self.text_test.delete("1.0",tk.END)
        
        # 获取EntrySingleFilePath 的值
        spc_fullname = self.EntrySingleFilePath.get()
        s = "开始 "+os.path.basename(spc_fullname)+" 的 ok 格式测试\n"
        self.text_test.insert(tk.END,s)
        file_info,cursor="",""
        try:
            file_info,cursor = parse_scp(spc_fullname)
            self.text_test.insert(tk.END,"ok 格式:\n")
        except Exception  as ex:
            self.text_test.insert(tk.END,"分析文件出错:\n")
            self.text_test.insert(tk.END,ex)
            self.text_test.insert(tk.END,"\n")
            return
        
        # 获取 self.text_ng_format 的text值
        ok_format = self.text_ok_format.get("1.0",tk.END)
        ok_format = ok_format.strip()
        ok_format = ok_format.replace('\n',' ')
        ok_format = ok_format.strip(',')
        r = okRows(ok_format,cursor)
        # 如果r是列表，则 拼接成 字符串
        if isinstance(r,list):
            for i in r:
                self.text_test.insert(tk.END,",".join(i)+"\n")
        else:
            self.text_test.insert(tk.END,r+"\n")
        self.text_test.insert(tk.END,"\n分析结束\n")
    
    def get_ok_format(self):
        ok_format = self.text_ok_format.get("1.0",tk.END)
        ok_format = ok_format.strip()
        ok_format = ok_format.replace('\n',' ')
        ok_format = ok_format.strip(',')
        return ok_format
    
    def get_ng_format(self):
        ng_format = self.text_ng_format.get("1.0",tk.END)
        ng_format = ng_format.strip()
        ng_format = ng_format.replace('\n',' ')
        ng_format = ng_format.strip(',')
        return ng_format
    
    def saveNgFormat(self):
        self.config.set('FMT', 'Fail', self.get_ng_format())
        self.save_config()
    
    def saveOkFormat(self):
        self.config.set('FMT', 'Pass', self.get_ok_format())
        self.save_config()
    
    def setNgDefault(self):
        ngDefaultFormat='"TEST:"||[ProgramName],[BoardID],[BoardID]||[BlockNo],[StartTime],[MachineName],"NoData","Fail",[OPJudge],[PartsName] as LibPartsName,[RefName],[StepCenterX],[StepCenterY],[NgReason],[BlockNo],[LaneNo],[RSOperatorName],[ImageFile] as newImageFile,[Lot]'
        self.text_ng_format.delete("1.0",tk.END)
        self.text_ng_format.insert(tk.END,ngDefaultFormat)
    
    def setOkDefault(self):
        okDefaultFormat='"TEST:"||[ProgramName],[BoardID],[BoardID]||[BlockNo],[StartTime],[MachineName],"NoData","Pass",[OPJudge],[Lot]'
        self.text_ok_format.delete("1.0",tk.END)
        self.text_ok_format.insert(tk.END,okDefaultFormat)

    def chooseSFPPath(self):
        path = tk.filedialog.askdirectory()
        if not path:
            return        
        self.EntrySFP.delete(0,tk.END)
        self.EntrySFP.insert(0,path)

    def chooseDFPPath(self):
        path = tk.filedialog.askdirectory()
        if not path:
            return        
        self.EntryDFP.delete(0,tk.END)
        self.EntryDFP.insert(0,path)
    
    def chooseEFPPath(self):
        path = tk.filedialog.askdirectory()
        if not path:
            return        
        self.EntryEFP.delete(0,tk.END)
        self.EntryEFP.insert(0,path)

    def choosePFPPath(self):
        path = tk.filedialog.askdirectory()
        if not path:
            return        
        self.EntryPFP.delete(0,tk.END)
        self.EntryPFP.insert(0,path)

    # endregion
    def save(self):
        # 获取 EntrySFP 的值
        self.config.set('PATH', 'spath', self.EntrySFP.get())
        self.config.set('PATH', 'dpath', self.EntryDFP.get())
        self.config.set('PATH', 'epath', self.EntryEFP.get())
        self.config.set('PATH', 'ppath', self.EntryPFP.get())
        
        adminPassword = self.EntryAdminPassword.get()
        userPassword = self.EntryUserPassword.get()
        if adminPassword != '':
            # 计算 adminPassword 的 md5
            adminPassword = hashlib.md5(adminPassword.encode('utf-8')).hexdigest()
            self.config.set('password', 'admin', adminPassword)
        if userPassword != '':
            userPassword = hashlib.md5(userPassword.encode('utf-8')).hexdigest()
            self.config.set('password', 'user', userPassword)
        # 获取  spinboxSeconds 的值
        self.config.set('TIME', 'seconds', self.spinboxSeconds.get())
        self.save_config()
    
if __name__ == "__main__":
    win = FormAdmin(master=Tk())
    win.mainloop()
    
    